﻿// <copyright file="Program.cs" company="EDD Solutions Ltd.">
// Copyright (c) EDD Solutions Ltd. 2010.
// </copyright>
// <author>$Author$</author>
// <date>$Date$</date>
// <revision>$Revision$</revision>
namespace Sharepoint.Manipulator.Net.SvnHook.PostCommit
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Text;
    using System.Collections.Generic;

    /// <summary>
    /// Class representing a program to handle Subversion PostCommit hook requests.
    /// </summary>
    /// <remarks>Based on work by Troy Hunt for Subversion hooks in .NET</remarks>
    /// <see cref="http://www.troyhunt.com/2010/02/creating-subversion-pre-commit-hooks-in.html"/>
    public class Program
    {
        /// <summary>
        /// Program entry point
        /// </summary>
        /// <param name="args">the parameters passed to the program.</param>
        public static void Main(string[] args)
        {
            string repos = args[0];
            string rvn = args[1];
            string format = "r";
            if (args.Length == 3)
            {
                format = args[2];
            }

            string log = GetSvnLookOutput(repos, format, rvn, "log");
            string changedPaths = GetSvnLookOutput(repos, format, rvn, "changed");
            SetMessage(log, changedPaths, rvn);
            int exitCode = 0;

            Environment.Exit(exitCode);
        }

        /// <summary>
        /// Call to SvnLook to identify transaction details.
        /// </summary>
        /// <param name="repos">the repository</param>
        /// <param name="numberFormat">r/t revision or transaction</param>
        /// <param name="number">the transaction/revision number</param>
        /// <param name="subcommand">the sub commmand</param>
        /// <returns>the svnlook generated string</returns>
        private static string GetSvnLookOutput(string repos, string numberFormat, string number, string subcommand)
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo
            {
                FileName = "svnlook.exe",
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                Arguments = String.Format("{0} -{1} \"{2}\" \"{3}\"", subcommand, numberFormat, number, repos)
            };

            Process process = Process.Start(processStartInfo);
            string output = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            return output;
        }

        /// <summary>
        /// Validate Log Messages
        /// </summary>
        /// <param name="files">the list of files altered</param>
        /// <param name="rvn">the revision number</param>
        /// <param name="log">the log message.</param>
        /// <returns>an error message or null if theare no errors.</returns>
        private static string SetMessage(string log, string files, string rvn)
        {
            Dictionary<string, StringBuilder> updates = new Dictionary<string, StringBuilder>();
            StringBuilder messagebuffer = null;
            string url = null;
            string[] lines = log.ToLower().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in lines)
            {
                if (line.StartsWith("http"))
                {
                    messagebuffer = new StringBuilder();
                    url = line;
                    updates.Add(url, messagebuffer);
                }

                if (messagebuffer != null && !line.Equals(url))
                {
                    messagebuffer.AppendLine(line);
                }
            }

            
            foreach (string updateUrl in updates.Keys)
            {
                messagebuffer = new StringBuilder();
                messagebuffer.AppendLine("Revision:" + rvn + ":");
                messagebuffer.AppendLine(updates[updateUrl].ToString());
                messagebuffer.AppendLine(files);
                IOperation update = new Update();
                update.ParseParameters(new string[] { updateUrl, "Comments=" + messagebuffer.ToString() });
                update.Run();
            }

            return null;
        }
    }
}
